package com.tarena.lbs.basic.web.service;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.dao.repository.AdminRepository;
import com.tarena.lbs.basic.web.dao.repository.UserGroupRepository;
import com.tarena.lbs.basic.web.dao.repository.UserTagsRepository;
import com.tarena.lbs.basic.web.thread.AuthenticationUtil;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.param.UserGroupParam;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.UserGroupPO;
import com.tarena.lbs.pojo.basic.po.UserTagsPO;
import com.tarena.lbs.pojo.basic.query.UserGroupQuery;
import com.tarena.lbs.pojo.basic.vo.UserGroupVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserGroupService {
    @Autowired
    private UserGroupRepository userGroupRepository;
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private UserTagsRepository userTagsRepository;
    public PageResult<UserGroupVO> userGroupPage(UserGroupQuery query) throws BusinessException {
        //1.组织一个假的pageResult 除了列表objects属性其他都赋值
        PageResult<UserGroupVO> voPage=assemblePageResult();
        //2.提供持久层所需的查询条件 给businessId 从登录用户认证对象入手获取
        Integer businessId=getBusinessId();
        //3.调用持久层 获取列表数据 select * from lbs_user_group where business_id=#{}
        List<UserGroupPO> pos=getUserGroupsByBusinessId(businessId);
        //4.封装返回
        List<UserGroupVO> vos=null;
        if (CollectionUtils.isNotEmpty(pos)){
            vos=pos.stream().map(po->{
                UserGroupVO vo=new UserGroupVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    private List<UserGroupPO> getUserGroupsByBusinessId(Integer businessId) {
        //组织一个QueryWrapper
        QueryWrapper<UserGroupPO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("business_id",businessId);
        //调用仓储层查询 返回结果
        return userGroupRepository.list(queryWrapper);
    }

    private Integer getBusinessId() throws BusinessException {
        //1 取得认证对象
        UserPrinciple userPrinciple = AuthenticationUtil.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户解析认证失败"));
        //2 拿到后台登录的adminId 读取admin详情 有字段businessId
        AdminPO adminPO = adminRepository.getById(userPrinciple.getId());
        Asserts.isTrue(adminPO==null,new BusinessException("-2","商家账号不存在"));
        return adminPO.getBusinessId();
    }

    private PageResult<UserGroupVO> assemblePageResult() {
        PageResult<UserGroupVO> voPage=new PageResult<>(1,10);
        voPage.setTotal(100L);
        return voPage;
    }

    public void addUserGroup(UserGroupParam param) throws BusinessException {
        //1.新增的 人群 应该保证 名称不重复
        Integer businessId = getBusinessId();
        //1.1同一个商家 下的人群 名称不能重复 绑定的标签不重复(有点复杂了) groupName businessId
        checkGroupRepeat(param.getGroupName(), businessId);
        //1.2全局的名称 不能重复, 商家下的标签绑定不能重复
        //2.封装po数据 写入到数据库表格
        saveUserGroup(param,businessId);
    }

    private void saveUserGroup(UserGroupParam param, Integer businessId) {
        //1.组织一个po 缺少的属性补充完整 businessId createAt
        UserGroupPO po=new UserGroupPO();
        BeanUtils.copyProperties(param,po);
        po.setBusinessId(businessId);
        po.setCreateAt(new Date());
        //2.调用仓储层新增
        userGroupRepository.save(po);
    }

    private void checkGroupRepeat(String groupName, Integer businessId) throws BusinessException {
        //select count(0) from lbs_user_group where group_name=#{} and business_id=#{}
        QueryWrapper query=new QueryWrapper();
        query.eq("group_name",groupName);
        query.eq("business_id",businessId);
        long count = userGroupRepository.count(query);
        Asserts.isTrue(count>0,new BusinessException("-2","人群名称重复"));
    }

    /**
     * 在这个业务方法中,我们需要使用userId 查询用户关联的所有标签id集合 然后在根据businessId和标签集合
     * 查询用户所属的用户人群范围
     * @param userId
     * @param businessId
     * @return
     */
    public List<Integer> getUserGroupIds(Integer userId, Integer businessId) {
        List<Integer> userGroupIds=null;
        //使用关联查询 也能实现业务 但是关联查询会锁表 2c业务 尽可能不使用
        //1.使用userId 查询 tagIds select * from lbs_user_tags where user_id=#{}
        List<UserTagsPO> userTagsPos=getUserTags(userId);
        List<Integer> userTagsId=null;
        if (CollectionUtils.isNotEmpty(userTagsPos)){
            userTagsId=userTagsPos.stream().map(po->{return po.getTagId();}).collect(Collectors.toList());
        }else{
            return userGroupIds;
        }
        log.info("当前用户:{},关联的标签ids:{}",userId,userTagsId);
        //2.在利用tagIds 和 businessId 查询人群列表 select * from lbs_user_group
        //where business_id=#{} and(FIND_IN_SET() OR FIND_IN_SET())
        List<UserGroupPO> userGroupPos=getuserGroupsByTagsAndBusinessId(userTagsId,businessId);
        if (CollectionUtils.isNotEmpty(userGroupPos)){
            userGroupIds=
                    userGroupPos.stream().map(po->{
                        return po.getId();
                    }).collect(Collectors.toList());
        }
        log.info("当前用户:{},所归属的用户人群:{}",userId,userGroupIds);
        //3.封装返回 人群的列表的id
        return userGroupIds;
    }

    private List<UserGroupPO> getuserGroupsByTagsAndBusinessId(List<Integer> userTagsId, Integer businessId) {
        //select * from lbs_user_group
        //where business_id=#{} and (FIND_IN_SET() OR FIND_IN_SET())
        //手写 mybatis 映射文件
        return userGroupRepository.getUserGroups(userTagsId,businessId);
    }

    private List<UserTagsPO> getUserTags(Integer userId) {
        // lbs_user_tag 用户标签关联表 使用userId 查询 数组
        //select * from lbs_user_tags where user_id=#{}
        QueryWrapper<UserTagsPO> query=new QueryWrapper<>();
        query.eq("user_id",userId);
        return userTagsRepository.list(query);
    }
}
